﻿#region File Description
///////////////////////////////////////////////////////////////////////////////
/// \file Node.cs
/// \brief This file stores the Node class
/// \note This should be sublclassed in application to provide loading functionality
/// \author Bradley Mclain, Steven Duda
/// \date 15/5/2010
/// \remarks Copyright(c) 2010 LM01 Project Group (Animus Games - ViralFlux)
/// \remarks Some Rights Reserved.
/// Licenced under: Microsoft Reciprocal License (Ms-RL)
/// For More Information see: www.microsoft.com/opensource/licenses.mspx
///////////////////////////////////////////////////////////////////////////////
#endregion

#region Using Statements
    using System.Collections.Generic;
#endregion

namespace PropagationEngine
{
    /// <summary>
    /// \class Node
    /// \brief This class provides the generic Node class
    /// \note It should be subclassed in application
    /// \author Bradley Mclain, Steven Duda
    /// \date 15/5/2010
    /// </summary>
    public class Node
    {
        #region Attributes

        //protected int magnitude; //! \todo Magnitude to be implemented further

        #endregion

        #region Properties

        public int ID { get; set; }

        public int Magnitude { get; set; }
        public Properties Properties { get; set; }
        public List<Edge> IncomingEdges {get; set; }
        public List<Edge> OutgoingEdges {get; set; }
        public List<Transmission> TransmissionsList {get; private set; }

        #endregion

        #region Methods

        /// <summary>
        /// \author Bradley Mclain, Steven Duda
        /// \brief Constructor for Node
        /// \date 15/05/2010
        /// </summary>
        public Node()
        {
            this.Magnitude = 0; //Should be Initialised to 0 by runtime anyways
            this.TransmissionsList = new List<Transmission>();
        }

        /// <summary>
        /// \author Steven Duda
        /// \brief Overloaded Constructor for Node - includes id parameter
        /// \param id Unique Node identifer
        /// \date 18/06/2010
        /// </summary>
        public Node(int id)
        {
            this.Magnitude = 0;  //Should be Initialised to 0 by runtime anyways
            this.ID = id;
            this.TransmissionsList = new List<Transmission>();
        }

        /// <summary>
        /// \author Steven Duda
        /// \brief Overloaded Constructor for Node - includes both parameters
        /// \param id Unique Node identifer
        /// \param magnitude Magnitude of the Node
        /// \date 18/06/2010
        /// </summary>
        public Node(int id, int magnitude)
        {
            this.ID = id;
            this.Magnitude = magnitude;
            this.TransmissionsList = new List<Transmission>();
        }

        /// <summary>
        /// \author Bradley Mclain, Steven Duda
        /// \brief First part of tick cycle, does external transmission(spread)
        /// \note Will only add a Transmission, if the SpreadCount > 0
        /// \date 15/05/2010
        /// </summary>
        public void Tick1()
        {
            //For each transmission check if it can spread to any adjacent nodes
            foreach (Transmission transmission in TransmissionsList)
            {
                if (OutgoingEdges != null)
                {
                    foreach (Edge edge in OutgoingEdges)
                    {
                        int amount = Ecosystem.ruleset.CheckExternalSpread(edge.StartNode, edge.EndNode, transmission);
                        if (amount > 0)
                        {
                            edge.Add(new Transmission(transmission.ContainedEntity, amount));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// \author Bradley Mclain, Steven Duda
        /// \brief Second part of tick cycle, does internal transmission(spread)
        /// \date 15/05/2010
        /// </summary>
        public void Tick2()
        {
            //! \warning Do Not attempt to simplify this!
            foreach (Transmission transmission in TransmissionsList)
            {
                int amount = Ecosystem.ruleset.CheckInternalSpread(this, transmission);

				transmission.Amount += amount;
            }
            //After all internal calculations, perform a cleanup
            Ecosystem.ruleset.Cleanup(this);

            //count entities
            foreach (Transmission t in TransmissionsList)
                t.ContainedEntity.Count++;
        }



        /// <summary>
        /// \author Steven Duda
        /// \brief Virtual Tick3
        /// \date 07/08/2010
        /// </summary>
        public void Tick3()
        {
            Ecosystem.ruleset.EntityInteraction(this);
        }

        /// <summary>
        /// \author Bradley Mclain, Steven Duda
        /// \brief Places the given entity in the transmission list according to its power
        /// \param transmission The transmission to place
        /// \date 15/05/2010
        /// \todo Order according to power
        /// </summary>
        public void Transmit(Transmission transmission)
        {
            //Check if already transmitted by this entity
            Transmission matching = this.TransmissionsList.Find(item => item.ContainedEntity.ID == transmission.ContainedEntity.ID);
            
            //If we find it add to exisiting, else make new transmission
            if (matching != null)
            {
                matching.Amount += transmission.Amount;
            }
            else
            {   
                this.TransmissionsList.Add(transmission);

                if(!Ecosystem.entities.ContainsKey(transmission.ContainedEntity.ID))
                    Ecosystem.entities.Add(transmission.ContainedEntity.ID, transmission.ContainedEntity); //add to global list of entities
            }
        }

        /// <summary>
        /// \author Steven Duda
        /// \brief Base Implementation: Clears the Node's Transmission List
        /// \date 05/08/2010
        /// </summary>
        public virtual void Clear()
        {
            this.TransmissionsList.Clear();
        }

        #endregion

    }
}
